package com.hmall.gateway.routers;

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONException;
import cn.hutool.json.JSONUtil;
import com.alibaba.cloud.nacos.NacosConfigManager;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

@Slf4j
@Component
@RequiredArgsConstructor
public class DynamicRouteLoader {

    private final NacosConfigManager nacosConfigManager;
    private final RouteDefinitionWriter routeDefinitionWriter;
    private final ApplicationEventPublisher applicationEventPublisher;

    private static final String DATA_ID = "gateway-routes";
    private static final String GROUP = "DEFAULT_GROUP";
    private Set<String> routeIds= new HashSet<>();
    @PostConstruct
    public void initRouteConfigListener() throws NacosException{
        log.info("初始化Nacos路由配置监听器");
        String configInfo = nacosConfigManager.getConfigService().getConfigAndSignListener(DATA_ID, GROUP, 5000, new Listener() {
            @Override
            public Executor getExecutor() {
                return null;
            }
            @Override
            public void receiveConfigInfo(String configInfo) {
                log.info("接收到Nacos配置变更: {}", configInfo);
                updateConfigInfo(configInfo);
            }
        });
        log.info("初始化路由配置: {}", configInfo);
        updateConfigInfo(configInfo);
    }
    public void updateConfigInfo(String configInfo){
        log.info("开始更新路由配置: {}", configInfo);
        try {
            List<RouteDefinition> list = JSONUtil.toList(configInfo, RouteDefinition.class);
            
            // 删除旧的路由
            for (String routeId : routeIds) {
                routeDefinitionWriter.delete(Mono.just(routeId)).subscribe();
            }
            routeIds.clear();
            
            // 添加新的路由
            for (RouteDefinition routeDefinition : list) {
                routeDefinitionWriter.save(Mono.just(routeDefinition)).subscribe();
                routeIds.add(routeDefinition.getId());
            }
            
            // 发布路由刷新事件，这是关键步骤！
            applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this));
            log.info("路由配置更新完成，共更新{}个路由", list.size());
            
        } catch (JSONException e) {
            log.error("解析路由配置失败: {}", configInfo, e);
        } catch (Exception e) {
            log.error("更新路由配置失败", e);
        }
    }

}
